package se.emilsjolander.library;

import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.render.PixelMapHolder;
import ohos.agp.utils.Color;
import ohos.agp.utils.LayoutAlignment;
import ohos.agp.utils.RectFloat;
import ohos.app.Context;
import ohos.media.image.PixelMap;

public class GlanceFoldShading implements FoldShading {

  private static final int SHADOW_COLOR = Color.BLACK.getValue();
  private static final int SHADOW_MAX_ALPHA = 192;

  private final Paint solidShadow;

  private final Paint glancePaint;
  private final PixelMap glance;
  private final RectFloat glanceFrom;
  private final RectFloat glanceTo;

  public GlanceFoldShading(PixelMap glance) {
    solidShadow = new Paint();
    solidShadow.setColor(new Color(SHADOW_COLOR));

    this.glance = glance;
    glancePaint = new Paint();
    glancePaint.setDither(true);
    glancePaint.setFilterBitmap(true);
    glanceFrom = new RectFloat();
    glanceTo = new RectFloat();
  }

  /**
   * @deprecated Use {@link #GlanceFoldShading(PixelMap)} instead.
   */
  @SuppressWarnings({"UnusedParameters", "unused"}) // Public API
  @Deprecated
  public GlanceFoldShading(Context context, PixelMap glance) {
    this(glance);
  }

  @Override
  public void onPreDraw(Canvas canvas, RectFloat bounds, float rotation, int gravity) {
    // No-op
  }

  @Override
  public void onPostDraw(Canvas canvas, RectFloat bounds, float rotation, int gravity) {
    float intensity = getShadowIntensity(rotation, gravity);

    if (intensity > 0f) {
      float alpha = SHADOW_MAX_ALPHA * intensity / 255f;
      solidShadow.setAlpha(alpha);
      canvas.drawRect(bounds, solidShadow);
    }

    boolean isDrawGlance = computeGlance(bounds, rotation, gravity);
    if (isDrawGlance) {
      canvas.drawPixelMapHolderRect(new PixelMapHolder(glance), glanceFrom, bounds, glancePaint);
    }
  }

  private float getShadowIntensity(float rotation, int gravity) {
    float intensity = 0f;
    if (gravity == LayoutAlignment.TOP) {
      if (rotation > -90f && rotation < 0f) { // (-90; 0) - Rotation is applied
        intensity = -rotation / 90f;
      }
    }
    return intensity;
  }

  private boolean computeGlance(RectFloat bounds, float rotation, int gravity) {
    if (gravity == LayoutAlignment.BOTTOM || gravity == LayoutAlignment.START) {
      if (rotation > 0f && rotation < 90f) { // (0; 90) - Rotation is applied
        final float aspect = (float) glance.getImageInfo().size.width / (float) bounds.getWidth();

        // Computing glance offset
        final int distance = (int) (bounds.getHeight() * ((rotation - 60f) / 15f));
        final int distanceOnGlance = (int) (distance * aspect);

        // Computing "to" bounds
        int scaledGlanceHeight = (int) (glance.getImageInfo().size.height / aspect);
        glanceTo.modify(bounds.left, bounds.top + distance,
            bounds.right, bounds.top + distance + scaledGlanceHeight);

        if (!glanceTo.isIntersect(bounds)) {
          // Glance is not visible
          return false;
        }

        // Computing "from" bounds
        int scaledBoundsHeight = (int) (bounds.getHeight() * aspect);
        glanceFrom.modify(0, -distanceOnGlance, glance.getImageInfo().size.width,
            -distanceOnGlance + scaledBoundsHeight);

        return glanceFrom.isIntersect(0, 0, glance.getImageInfo().size.width,
            glance.getImageInfo().size.height);
      }
    }

    return false;
  }


}
